package org.lh.ibernate.core.impl;

import org.lh.ibernate.annotation.Column;
import org.lh.ibernate.annotation.Table;
import org.lh.ibernate.core.IFieldHandle;
import org.lh.ibernate.core.IInsert;
import org.lh.ibernate.utils.impl.DbUtil;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import static org.lh.ibernate.common.CommonUtil.printSql;

public class InsertUtil<T> implements IInsert<T> {

    private IFieldHandle iFieldHandle=new FieldHandle();

    @Override
    public void save(T obj) throws Exception {
        StringBuffer sql=new StringBuffer("insert into ");
        Class clazz=obj.getClass();
        boolean tableNameExist=clazz.isAnnotationPresent(Table.class);
        if(tableNameExist){
            Table annoTableName= (Table) clazz.getAnnotation(Table.class);
            String tableName=annoTableName.name(); //获取表名称
            sql.append(tableName).append(" (");
            List<String> fieldNameList=iFieldHandle.getFieldNameHasColumnAnnotation(obj);
            int size=fieldNameList.size();
            for (int index=0;index<size;index++) {
                if(index<size-1){
                    sql.append(fieldNameList.get(index)+",");
                }else{
                    sql.append(fieldNameList.get(index)+")");
                }
            }
            sql.append(" values (");
            for(int index=0;index<size-1;index++){
                sql.append("?,");
            }
            sql.append("?)");
            printSql(new String(sql));
            List<Object> valueList=new ArrayList<>();
            valueList=iFieldHandle.getAttrFromFieldHasColumnAnnotation(obj);
            DbUtil dbUtil=new DbUtil();
            dbUtil.executeUpdate(new String(sql),valueList);
        }else{
            throw  new Exception("databases name not exist!");
        }
    }



    //批量插入操作
    public List<T> batchInsert(List<T> objList) throws Exception {
        if(objList.size()>0){
            T obj=objList.get(0);
            List<Object> objectList=TypeConvertHandle(objList);
            batchInsert(objectList,obj.getClass());
        }
        return objList;
    }

    private List<Object> batchInsert(List<Object> objList,Class clazz) throws Exception {
        if(objList.size()>0) {
            if(clazz.isAnnotationPresent(Table.class)) {
                DbUtil db=new DbUtil();
                Table table= (Table) clazz.getAnnotation(Table.class);
                String tableName=table.name();
                StringBuffer sql = new StringBuffer("insert into ");
                sql.append(tableName).append(" values (");
                for(int j=0;j<countFieldNums(clazz)-1;j++){
                    sql.append("?,");
                }
                sql.append("?)");
                db.batchInsert(sql.toString(), (List<Object>) objList,countFieldNums(clazz),objList.size()/countFieldNums(clazz));
            }
        }
        return objList;
    }

    //获取一个对象有多少个属性
    private  int countFieldNums(Class clazz){
        return clazz.getDeclaredFields().length;
    }

    //集合转换器，用于将userslist的全部内容转换为list集合
    private List<Object> TypeConvertHandle(List<T> list) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        T obj=list.get(0);
        Class clazz=obj.getClass();
        List<Object> objectList=new ArrayList<>();
        for (T t : list) {
            obj=t;
            if(clazz.isAnnotationPresent(Table.class)){
                Field[] fields=clazz.getDeclaredFields();
                for (Field field : fields) {
                    if(field.isAnnotationPresent(Column.class)){
                        String methodName="get"+field.getName().substring(0,1).toUpperCase()+field.getName().substring(1);
                        Method method=clazz.getMethod(methodName);
                        //获取相应字段的value值
                        Object value=method.invoke(obj);
                        objectList.add(value);
                    }
                }
            }
        }
        return objectList;
    }

}
